package com.xhj.myframe.myspring.zhouyu;

import lombok.Data;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
/**
 * -
 *
 * @author 见见 pure_xhj@163.com @Date 2021-08-28 @Time 18:22
 */
public class ZhouyuApplicationContext {

  private Class configClass;
  private ConcurrentHashMap<String, Object> singletonObjects = new ConcurrentHashMap<>();
  private ConcurrentHashMap<String, BeanDefination> beanDefinationMap = new ConcurrentHashMap();

  public ZhouyuApplicationContext(Class configClass) {

    this.configClass = configClass;

    // 解析配置类
    MyComponentScan myComponentScan =
        (MyComponentScan) configClass.getDeclaredAnnotation(MyComponentScan.class);
    String path = myComponentScan.value();
    System.out.println("myComponentScan.value() = " + path);

    path = path.replace('.', '/');
    ClassLoader classLoader = ZhouyuApplicationContext.class.getClassLoader();
    URL resource = classLoader.getResource(path);
    File file = new File(resource.getFile());
    if (file.isDirectory()) {
      File[] files = file.listFiles();
      for (File f : files) {
        if (f.getName().endsWith(".class")) {
          String absolutePath = f.getAbsolutePath();
          String className =
              absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
          className = className.replace('\\', '.');
          System.out.println("className = " + className);
          try {
            Class<?> clazz = classLoader.loadClass(className);
            if (clazz.isAnnotationPresent(MyComponent.class)) {
              // 当前类是一个bean
              String beanName = clazz.getDeclaredAnnotation(MyComponent.class).value();

              BeanDefination beanDefinition = new BeanDefination();
              if (clazz.isAnnotationPresent(MyScope.class)) {
                beanDefinition.setScope(clazz.getAnnotation(MyScope.class).value());
              }
              beanDefinationMap.put(beanName, beanDefinition);
            }
          } catch (Exception e) {
            e.printStackTrace();
          }
        }
      }
    }
    // 扫描
    // BootStrap-->jre/lib
    // Ext-->jre/ext/lib
    // App-->classpath

  }

  public Object getBean(String beanName) {
    if (beanDefinationMap.containsKey(beanName)) {
      BeanDefination beanDefination = beanDefinationMap.get(beanName);
      if (beanDefination.getScope().equals("singleton")) {
        Object o = singletonObjects.get(beanName);
        if (o == null) {
          o = createBean(beanName);
          singletonObjects.put(beanName, o);
        }
        return o;
      } else {
        return createBean(beanName);
      }
    }
    return null;
  }

  private Object createBean(String beanName) {
    BeanDefination beanDefination = beanDefinationMap.get(beanName);
    Class clazz = beanDefination.getClass();
    try {
      UserService userServiceBean = UserService.class.getDeclaredConstructor().newInstance();
      return userServiceBean;
    } catch (InstantiationException e) {
      e.printStackTrace();
    } catch (IllegalAccessException e) {
      e.printStackTrace();
    } catch (InvocationTargetException e) {
      e.printStackTrace();
    } catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
    return null;
  }
}

@Data
class BeanDefination {
  private String scope;
}
